//  Copyright (c) 2008  Yoong-ki Ahn & Youngjin Kim < mexif@googlegroups.com>
//  See the enclosed file COPYING for license information (MIT Licence).
//  If you did not receive this file,
//  see http://www.opensource.org/licenses/mit-license.php.



#include "stdafx.h"
#include "exiftabext.h"
#include <atlstr.h>
#include <PropTree.h>
#include <fill_exif.h>

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

// CExifTabExt


HRESULT STDMETHODCALLTYPE CExifTabExt::Initialize( LPCITEMIDLIST pidlFolder, LPDATAOBJECT pDataObj, HKEY hProgID )
{
	{
		INITCOMMONCONTROLSEX iccex = { sizeof(INITCOMMONCONTROLSEX), ICC_DATE_CLASSES };

		// Init the common controls.
		ATLVERIFY( InitCommonControlsEx ( &iccex ) );
	}

	// Read the list of items from the data object.  They're stored in HDROP
	// form, so just get the HDROP handle and then use the drag 'n' drop APIs
	// on it.
	FORMATETC etc = { CF_HDROP, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
	STGMEDIUM stg;
	if ( FAILED( pDataObj->GetData ( &etc, &stg ) ))
		return E_INVALIDARG;

	// Get an HDROP handle.
	HDROP hdrop = (HDROP) GlobalLock ( stg.hGlobal );

	if ( NULL == hdrop )
	{
		ReleaseStgMedium ( &stg );
		return E_INVALIDARG;
	}

	// Determine how many files are involved in this operation.
	UINT uNumFiles = DragQueryFile ( hdrop, 0xFFFFFFFF, NULL, 0 );
	TCHAR     szFile[MAX_PATH];
	for ( UINT uFile = 0; uFile < uNumFiles; uFile++ )
	{
		// Get the next filename.
		if ( 0 == DragQueryFile ( hdrop, uFile, szFile, MAX_PATH ) )
			continue;

		// Skip over directories.  We *could* handle directories, since they
		// keep the creation time/date, but I'm just choosing not to do so
		// in this example.
		if ( PathIsDirectory ( szFile ) )
			continue;

		LPCTSTR ext = PathFindExtension( szFile );
		if ( ext == 0 )
			continue;

		if ( StrCmpI( ext, TEXT(".jpg") ) != 0 )
			continue;

		// Add the filename to our list of files to act on.
		m_files.Add( szFile );

		//m_lsFiles.push_back ( szFile );
	}   // end for

	// Release resources.
	GlobalUnlock ( stg.hGlobal );
	ReleaseStgMedium ( &stg );

	//	EXIF tab can show one file.
	if ( m_files.GetCount() != 1 )
		return E_FAIL;



	return S_OK;
}

BOOL CALLBACK PropPageDlgProc ( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam );
UINT CALLBACK PropPageCallbackProc ( HWND hwnd, UINT uMsg, LPPROPSHEETPAGE ppsp );

struct FakeDialog
{
	CPropTree*		pTree;
	TCHAR			filepath[MAX_PATH];
};

HRESULT STDMETHODCALLTYPE CExifTabExt::AddPages( LPFNADDPROPSHEETPAGE lpfnAddPageProc, LPARAM lParam )
{
	PROPSHEETPAGE	psp;
	TCHAR			szPageTitle[MAX_PATH] = TEXT("Exif");

	FakeDialog*		fake = (FakeDialog*) malloc( sizeof(FakeDialog) );
	fake->pTree = 0;
	StrCpyN( fake->filepath, m_files.GetAt( 0 ), MAX_PATH );

	memset( &psp, 0, sizeof(psp) );
	psp.dwSize		= sizeof(PROPSHEETPAGE);
	psp.dwFlags		= PSP_USEREFPARENT | PSP_USETITLE | PSP_USECALLBACK;
	psp.hInstance	= _AtlBaseModule.GetResourceInstance();
	psp.pszTemplate = MAKEINTRESOURCE( IDD_EXIFTAB_PROPPAGE );
	psp.pszIcon     = 0;
	psp.pszTitle    = szPageTitle;
	psp.lParam      = (LPARAM) fake;
	//psp.lParam		= (LPARAM) sz
	psp.pfnDlgProc  = PropPageDlgProc;
	psp.pfnCallback = PropPageCallbackProc;
	psp.pcRefParent = (UINT*) &_pAtlModule->m_nLockCnt;

	HPROPSHEETPAGE	hPage = CreatePropertySheetPage ( &psp );
	if ( NULL != hPage )
	{
		// Call the shell's callback function, so it adds the page to
		// the property sheet.
		if ( !lpfnAddPageProc ( hPage, lParam ) )
			DestroyPropertySheetPage ( hPage );
	}

	return S_OK;
}

#define IDC_PROPERTYTREE			100

BOOL CALLBACK PropPageDlgProc ( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
{
	AFX_MANAGE_STATE(AfxGetStaticModuleState());  // init MFC

	BOOL bRet = FALSE;

	switch( uMsg )
	{
	case WM_INITDIALOG :
		{
			CWnd that;
			that.Attach( hwnd );

			LPPROPSHEETPAGE ppsp = (LPPROPSHEETPAGE) lParam;

			// PTS_NOTIFY - CPropTree will send notification messages to the parent window
			DWORD dwStyle = WS_CHILD|WS_VISIBLE|PTS_NOTIFY;
			CRect rc;
			that.GetClientRect( rc );
			
			CPropTree*  pTree = ((FakeDialog*) ppsp->lParam)->pTree;
			ATLASSERT( pTree == 0 );
			pTree = new CPropTree;
			SetWindowLong( hwnd, GWL_USERDATA, (LONG) pTree );

			pTree->Create( dwStyle, rc, &that, IDC_PROPERTYTREE );

			//	load file and register the items.
			fill_exif( pTree, ((FakeDialog*) ppsp->lParam)->filepath );

			//CPropTreeItem* pRoot;

			//pRoot = pTree->InsertItem(new CPropTreeItem());
			//pRoot->SetLabelText(_T("Properties"));
			//pRoot->SetInfoText(_T("This is a root level item"));
			//pRoot->Expand(); // have this item expanded by default

			bRet = true;
			that.Detach();
		}
		break;

	case WM_SIZE :
		{
resize_tree :
			CWnd that;
			that.Attach( hwnd );
			CRect rc;
			that.GetClientRect( rc );

			CPropTree*  pTree = (CPropTree*) GetWindowLong( hwnd, GWL_USERDATA );
			if ( pTree )
			{
				pTree->SetWindowPos(NULL, -1, -1, 
					rc.Width(), rc.Height(), SWP_NOMOVE|SWP_NOZORDER);	
			}

			that.Detach();
		}
		break;

	case WM_NOTIFY :
		//if ( ((LPNMHDR)lParam)->code == PTN_ITEMCHANGED )
		//{
		//	CWnd that;
		//	that.Attach( hwnd );
		//	CRect rc;
		//	that.GetClientRect( rc );

		//	CPropTree*  pTree = (CPropTree*) GetWindowLong( hwnd, GWL_USERDATA );

		//	that.Detach();
		//}
		return bRet;

	case WM_ERASEBKGND :
		bRet = true;
		break;

	case WM_ACTIVATE :
		break;
	}

	return bRet;
}

UINT CALLBACK PropPageCallbackProc ( HWND hwnd, UINT uMsg, LPPROPSHEETPAGE ppsp )
{
	AFX_MANAGE_STATE(AfxGetStaticModuleState());  // init MFC
	CPropTree*  pTree = ((FakeDialog*) ppsp->lParam)->pTree;

	if ( hwnd != 0 )
	{
		CWnd that;
		that.Attach( hwnd );

		if ( PSPCB_RELEASE == uMsg )
		{
			pTree->DestroyWindow();
			delete pTree;
			free( (void*) ppsp->lParam );
		}

		that.Detach();
	}

	return 1;
}
